﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Login.Models;
using Login.ASelectService;
using Login.OSIRISService;

namespace Login.Controllers
{
    /// <summary>
    /// The LoginController handles all actions that have to do
    /// with logging in and out.
    /// </summary>
    public class LoginController : Controller
    {
        /// <summary>
        /// Called when the user requests the Index action using
        /// GET.
        /// </summary>
        /// <returns>The view</returns>
        public ActionResult Index()
        {
            /* define empty controller to redirect to */
            string controller = "";

            /* if a student is logged in */
            if (Request.IsAuthenticated && Session["Details"] != null && Session["Details"] is StudentDetails)
            {
                /* set controller name */
                controller = "Home";
            }

            /* if a teacher is logged in */
            if (Request.IsAuthenticated && Session["Details"] != null && Session["Details"] is TeacherDetails)
            {
                /* set controller name */
                controller = "Student";
            }

            /* if the controller name is not empty */
            if (controller.Length > 0)
            {
                /* redirect to index action of controller */
                return RedirectToAction("Index", controller);
            }

            /* return the view */
            return View();
        }

        /// <summary>
        /// Called when the user submits the login form using POST.
        /// </summary>
        /// <param name="model">The LoginModel containing the username and password</param>
        /// <returns>Redirect or the view</returns>
        [HttpPost]
        public ActionResult Index(LoginModel model, string returnUrl)
        {
            /* if the model is valid */
            if (ModelState.IsValid)
            {
                /* create clients for A-Select and OSIRIS */
                ASelectServiceClient aselect = new ASelectServiceClient();
                OSIRISServiceClient osiris = new OSIRISServiceClient();

                /* hash the password */
                PasswordHasher hasher = new PasswordHasher();
                string passwordHash = hasher.Hash(model.Password);

                /* check login details */
                LoginResult loginResult = aselect.Login(model.Username, passwordHash);

                /* handle result */
                switch (loginResult)
                {
                    /* successful login */
                    case LoginResult.SUCCESSFUL:
                        /* get the type of account */
                        AccountDetails account = aselect.GetAccountDetails(model.Username);

                        /* define controller name */
                        string controller = "Home";

                        /* if the user is a student */
                        if (account.Role.Id == 1)
                        {
                            /* connect to local database */
                            AfstudeerregistratieDataContext database = new AfstudeerregistratieDataContext();

                            /* check if student is in local database */
                            IEnumerable<Student> students =
                                from foundStudent in database.Students
                                where foundStudent.Number == account.Number
                                select foundStudent;

                            /* declare StudentDetails */
                            StudentDetails student = null;

                            /* if the student does not exist */
                            if (students.Count() == 0)
                            {
                                /* fetch the student's details from OSIRIS */
                                student = osiris.GetStudentDetails(model.Username);

                                /* create a new Student */
                                Student newStudent = new Student();
                                newStudent.Number = student.Number;
                                newStudent.FirstName = student.FirstName;
                                newStudent.Prefix = student.Prefix;
                                newStudent.LastName = student.LastName;
                                newStudent.Email = student.Email;
                                newStudent.TelephoneNumber = student.TelephoneNumber;
                                newStudent.HasLoggedIn = true;

                                /* save student to database */
                                database.Students.InsertOnSubmit(newStudent);
                                database.SubmitChanges();
                            }
                            else
                            {
                                /* get student from query */
                                Student foundStudent = students.First();

                                /* modify student */
                                foundStudent.HasLoggedIn = true;

                                /* save changes */
                                database.SubmitChanges();

                                /* fill StudentDetails */
                                student = new StudentDetails();
                                student.Number = foundStudent.Number;
                                student.FirstName = foundStudent.FirstName;
                                student.Prefix = foundStudent.Prefix;
                                student.LastName = foundStudent.LastName;
                                student.Email = foundStudent.Email;
                                student.TelephoneNumber = foundStudent.TelephoneNumber;
                            }

                            /* save details in the session */
                            Session.Add("Details", student);

                            /* if the student is not linked to the Student role in the application */
                            if (!Roles.GetUsersInRole("Student").Contains(student.Number))
                            {
                                /* add the student to the Student role */
                                Roles.AddUserToRole(student.Number, "Student");
                            }
                        }
                        else
                        {
                            /* fetch the teacher details from OSIRIS */
                            TeacherDetails docent = osiris.GetTeacherDetails(model.Username);

                            /* save details in the session */
                            Session.Add("Details", docent);

                            /* overwrite controller */
                            controller = "Student";
                            
                            /* if the teacher is not linked to the Teacher role in the application */
                            if (!Roles.GetUsersInRole("Teacher").Contains(docent.Number))
                            {
                                /* add the teacher to the Teacher role */
                                Roles.AddUserToRole(docent.Number, "Teacher");
                            }
                        }

                        /* create session cookie */
                        FormsAuthentication.SetAuthCookie(model.Username, false);

                        /* redirect to default page */
                        return RedirectToAction("Index", controller);
                    /* username error */
                    case LoginResult.USERNAME_ERROR:
                        /* set error message in model */
                        ModelState.AddModelError("Username", "Het student-/docentnummer is niet bekend");
                        break;
                    /* password error */
                    case LoginResult.PASSWORD_ERROR:
                        /* set error message in model */
                        ModelState.AddModelError("Password", "Het ingevulde wachtwoord is incorrect");
                        break;
                    /* username empty */
                    case LoginResult.USERNAME_EMPTY:
                        /* set error message in model */
                        ModelState.AddModelError("Username", "Vul je student-/docentnummer in ");
                        break;
                    /* password empty */
                    case LoginResult.PASSWORD_EMPTY:
                        /* set error message in model */
                        ModelState.AddModelError("Password", "Vul je wachtwoord in");
                        break;
                    default:
                        break;
                }

                /* close connection to A-Select and OSIRIS */
                aselect.Close();
                osiris.Close();
            }

            /* return the view */
            return View(model);
        }

        /// <summary>
        /// Called when the user requests the Logoff action using
        /// GET.        
        /// </summary>
        /// <returns>Redirect to login page</returns>
        public ActionResult Logoff()
        {
            /* log out */
            FormsAuthentication.SignOut();

            /* delete details from session */
            Session["Details"] = null;

            /* redirect to login page */
            return RedirectToAction("Index", "Login");
        }
    }
}
